image.png

2D Image Processing - Exercise Sheet 1: Filters¶

The notebook guides you through the exercise. Read all instructions carefully.

  • Deadline: 16.05.2022 @ 23:59
  • Contact: Michael.Fuerst@dfki.de
  • Submission: As HTML Printout (see Exercise 0); filename is ex01_2DIP_group_XY.html, where XY is replaced by your group number.
  • Allowed Libraries: Numpy, OpenCV and Matplotlib (unless a task specifically states differently).
  • Copying or sharing code is NOT permitted and results in failing the exercise. However, you could compare produced outputs if you want to. (Btw, this includes copying code from the internet.)

0. Infrastructure: Cloud Image Loader¶

This is an image loader function, that loads the images needed for the exercise from the dfki-cloud into an opencv usable format. This allows for easy usage of colab, since you only need this notebook and no other files.

In [1]:
import cv2
import numpy as np
import matplotlib.pyplot as plt

import requests
from PIL import Image

def get_image(name, no_alpha=True):
    url = f'https://cloud.dfki.de/owncloud/index.php/s/THLirfoB6SYTetn/download?path=&files={name}'
    image = np.asarray(Image.open(requests.get(url, stream=True).raw))
    if no_alpha and len(image) > 2 and image.shape[2] == 4:
        image = image[:,:,:3]
    return image[:,:,::-1].copy()

1. Image Correlation & Template Matching¶

Theory: Correlation¶

What is meant by image Correlation? Explain it with the geometric interpretation. How to handle the pixel values at the boundaries?

Hint: Double click on the solution cell and you can enter your answer. Your answer must be within a single cell and keep the caption (i.e. **Solution:**) so we can find it. The cell supports Markdown (Cheatsheet) and LaTeX for formulas. To add a latex formula use $, for example: $f(x) = \sum_i x_i$ -> $f(x) = \sum_i x_i$.

Solution: Image Correlation is a measurement of the simlilarity between two images. When two images are given, one is the template and other is the coomplete image, the image correlation is applied to find where is the template in the given complete image.

Geometric Interpretation of Image Correlation:

Suppose x and y are two n-dimensional vectors:

$x = (x_1, x_2, … , x_{n})$ $y = (y_1, y_2, … , y_n)$

The dot product of x with y is defined as:

$ x.y = x_1 y_1 + x_2 y_2 +...+ x_n y_n$

$x. y =| x || y |cos(θ)$

$cos(θ)$ measures the similarity between x and y

$x. y =| x || y |cos(θ)$ or

$cos(θ) = \frac{x y}{|x| |y|}$

where,

$x y$ -> Cross-corelation

$|x| |y|$ -> division makes this a non-linear operation.

We have different techniques to handle the pixels at the boundaries namely mirror reflecting, adding constant values at the boundaries. In mirror refleccting we will add the values of the pixels which are present in the other side of the image and complete the operation In case of adding the constant values, we will replace the boundary values with zero and perform the operation.

Programming Task: Template Matching¶

Template Matching is a method for searching and finding the location of a template image in a larger image. It simply slides the template image over the input image (as in 2D convolution) and compares the template and patch of input image under the template image. Several comparison methods are implemented in OpenCV. You could use the predefined template functions or write the user defined functions.

Write a simple program to find a the given below template image from the given input image. The template matching function returns a grayscale image as an output, where each pixel denotes how much does the neighborhood of that pixel match with template image. If input image is of size (W x H) and template image is of size (w x h), output image will have a size of (W-w+1 , H-h+1).

Template:

template

Image:

messi

Hint: You can check the opencv documentation or implement the algorithm using numpy from scratch.

In [2]:
# Solution
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt




messi = get_image("messi.png")
template = get_image("messi_template.png")


top_left = (75,20)
bottom_right = (125, 80)
x, y= template.shape[:-1]

# TODO add your code including comments
# TODO find the template and visualize it on the image. The visualization should look somewhat like the example, just the correct patch...
#using the correlatiom coffeciant as the match template
met = eval('cv2.TM_CCOEFF')

output = cv.matchTemplate(messi,template,met)
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(output)


bottom_right1 = (max_loc[0] + y , max_loc[1] + x )

messi_template = cv2.rectangle(messi, max_loc, bottom_right1, (0,255,0), 2)
plt.imshow(messi_template[:,:,::-1])  # Do not forget the BGR to RGB for plotting...
plt.subplot(111),plt.imshow(output,cmap = 'gray')
plt.show()

The matchTemplate() function compares the image with a template using a Correlation Coefficient. This function tries to find the template present in the given image by taking the rows and column values of the main image. Once the values are matched it will be highlighted and gives the output. The output image is then converted into the gray scale where the output will be highlighted with bright white spot.


2. Image Smoothing and Image Filtering¶

Theory: Filtering¶

What is meant by Image Filtering? Please explain the difference between local filter and area/global filter, linear filter and non-linear filter, high-pass filter and low-pass filter with examples.

Explanation:

Image Filtering is a technique through which size, colours, shading and few other parameters applied to5 pixels to alter the existing image.

Local filters: These filters perform operations on pixels based on location, relation between the pixels and other features which is applied only on one block. These filters are has better edge recovery results. examples: 1. Image Sharpening and Blurring : Image sharpening is a method to increase and give them the sharper appearance while Image blurring is used to remove the noise which is present in the image.

Global Filters: These filters does operation on all the pixels of the image irrespective of the pixels location. It is applied to any number of blocks. examples:1. Brightening and Darkening : To change the appearance of image by changing brightness or darkness of the image.

     2. Contrast: changing ranges of light and dark by increasing or decreasing




Linear Filter: It is the process in which the targetted output pixel is the linear compbination of the neighbouring input pixel. It can be done using convolution and Fourier Transformation. examples: Gaussian Filter and Average Filter - Guassian filter is used to blur the image and remove the noise where the weight will be more concentrated towards the center pixel, meaning farther pixles will get less weight and the average filter is also used to remove the noise in which it will average the pixel values of all neighboring pixels.

Non-Linear Filter: It is the process, which operates on the ranking of the pixels in the spicified neighborhood. The targetted pixel will be replaced by the value corresponding to the choosen rank. examples: Median Filter: It is a process where it will sort the pixel values of the neighborhoods in which the original value will be replaced by the median value. It is used to remove noise from the image

High pass filter: A high pass filter allows high frequencies to pass through it and restricts low frequencies A high pass filter is used in examples where the image is needed to be sharpened. Low pass filter: A low pass filter allows low frequencies to pass through it and restricts high frequencies and a low pass filter is used in examples when the image is needed to be smoothened.

Programming Task: Gaussian vs Average Smoothing¶

Apply Gaussian and Average smoothing filters over given input image and play with the degree of smoothing parameter sigma as 3, 5 and 7 to observe it effect on the output.

Write a small description on the behaviour of the smoothing parameter. Explain using the images you generate.

In [3]:
# Solution
import cv2
import numpy as np
import matplotlib.pyplot as plt


lena = get_image("lena.png")
ROWS=1; COLS=3
plt.figure(figsize=(18,6))


# TODO add your code including comments
ablur = cv.blur(lena,(3,3)) #giving 3 to the kernel size and applying average filter function
ablur1 = cv.blur(lena,(5,5)) #giving 5 to the kernel size and applying average filter function
ablur2 = cv.blur(lena,(7,7)) #giving 7 to the kernel size and applying average filter function
plt.subplot(ROWS, COLS, 1) # Draw in first slot
plt.title("Average filter with kernel 3")
plt.imshow(ablur[:,:,::-1])
plt.subplot(ROWS, COLS, 2) # Draw in second slot
plt.title("Average filter with kernel 5")
plt.imshow(ablur1[:,:,::-1])
plt.subplot(ROWS, COLS, 3) # Draw in third slot
plt.title("Average filter with kernel 7")
plt.imshow(ablur2[:,:,::-1])
#plt.show()


plt.figure(figsize=(18,6))
gblur = cv.GaussianBlur(lena,(9,9),3,3) # we have kept the kernel size as 9x9 and given the sigma value as 3 and applied the Gaussian filter to the image
gblur1 = cv.GaussianBlur(lena,(9,9),5,5) # we have kept the kernel size as 9x9 and given the sigma value as 5 and applied the Gaussian filter to the image
gblur2 = cv.GaussianBlur(lena,(9,9),7,7) # we have kept the kernel size as 9x9 and given the sigma value as 7 and applied the Gaussian filter to the image


# Feel free to add more visualizations.
plt.subplot(ROWS, COLS, 1) # Draw in first slot
plt.title("Gaussian filter with sigma 3")
plt.imshow(gblur[:,:,::-1])
plt.subplot(ROWS, COLS, 2) # Draw in second slot
plt.title("Gaussian filter with sigma 5")
plt.imshow(gblur1[:,:,::-1])
plt.subplot(ROWS, COLS, 3) # Draw in third slot
plt.title("Gaussian filter with sigma 7")
plt.imshow(gblur2[:,:,::-1])# Do not forget the BGR to RGB for plotting...
plt.show()

Explanation:

In the above program where we have used the average and gaussian filter for the given image. At first, we have declared the image size along with rows and colums. Average Filter: we have applied the average filter function (cv.blur) on the given image with different kernel size. From the output we have explain that the increase in the size of the kernel, more will be the blurring of the image. kernel size having 7 is more blurred when compared to the kernel size 3. we have displayed those output in three columns mentioning the kernel size.

Gaussian Filter: we have applied the gaussian filter function (cv.gaussianblur) on the given image with different sigma value. Kernel size is also dependent on the bluring along with the sigma value. Whenever we change the kernel size and sigma value, based on that the output changes. we can see image with higher sigma value is more blurred with the image with lesser sigma value.

When compared the ouptputs of the average filter and gaussian, we observed that the gaussian filter is more efficent than the average filter


3. Image Noise and Image Sharpening¶

Theory: Noise Types¶

What is meant by noise in an image? Eplain three noises:

  1. Salt and pepper noise
  2. Impulse noise
  3. Gaussian noise

Solution:

Image noise can be defined as the unwanted traces in various image attributes such as colour, brightness etc. reducing the quality of the image.

The three types of noises are:

1.Salt and Pepper noise: This type of noisy image constists of random occurances of black and white pixels.

2.Impulse noise: This type of noise is similar to Salt & Pepper noise but contains only the salt part, i.e., white pixel occurance.

3.Gaussian noise: This type of noise is obtained from variations in intensity drawn from a Gaussian Normal Distribution.

Programming Task: Noise + Filter¶

Apply the three noises (above) on the images and then apply:

  1. Guassian Filter
  2. Average Filter
  3. Median Filter

Then explain: What can you observe in above images? What works well and what not and why?

In [4]:
# Solution
import cv2
import numpy as np
import matplotlib.pyplot as plt

def visualize_grid3x3(results):
    # Visualize the results in a 3x3 image matrix
    ROWS=3; COLS=3
    plt.figure(figsize=(18,18)) # Make a wide figure
    for idx, (title, image) in enumerate(results.items()):
        plt.subplot(ROWS, COLS, idx + 1)  # Select subplot
        plt.title(title)  # Set title to key of dict
        plt.imshow(image[:,:,::-1].astype('uint8'))  # BGR2RGB
    plt.show()

lena = get_image("lena.png")

#Salt noise (Impulse noise)
def sal_no(im):
    for i in range(1,nopi,10):
        y1=np.random.randint(r)
        x1=np.random.randint(c)
        im[x1][y1] = 255 #Set pixel to white
    return im

#Pepper noise
def pep_no(im):
    for i in range(1,nopi,10):
        y2=np.random.randint(r)
        x2=np.random.randint(c)
        im[y2][x2] = 0 #Set pixel to black
    return im

#Gaussian noise
def g_no(im):
    row,col,ch = im.shape
    mean = 0 #Mean
    var = 0.1 #Variance
    sig = var**0.5 #Sigma
    gg = np.random.normal(mean,sig,(row,col,ch)) #Guassian normal distribution
    gg = gg.reshape(row,col,ch)
    gaus = im + gg #Appending image with Gaussian distribution
    return gaus

r, c = lena.shape[:-1] #Dimensions of image
nopi = r*c #Number of pixels

#Calling the noise functions
lena_s = sal_no(lena)
lena_sp = pep_no(lena_s)
lena_g = g_no(lena)

ksize = (10,10) #Kernel size

#Gaussian Filter
lena_sp_g = cv2.GaussianBlur(lena_sp,(9,9),0)
lena_s_g = cv2.GaussianBlur(lena_s,(9,9),0)
lena_g_g = cv2.GaussianBlur(lena_g,(9,9),0)

#Average Filter
lena_sp_a = cv2.blur(lena_sp,ksize)
lena_s_a = cv2.blur(lena_s,ksize)
lena_g_a = cv2.blur(lena_g,ksize)

#Median Filter
lena_sp_m = cv2.medianBlur(lena_sp,5)
lena_s_m = cv2.medianBlur(lena_s,5)
lena_g_m = cv2.medianBlur(lena_s,5)

results = {
    "salt & pepper + gaussian": lena_sp_g,
    "salt & pepper + average": lena_sp_a,
    "salt & pepper + median": lena_sp_m,
    "impulse + gaussian": lena_s_g,
    "impulse + average": lena_s_a,
    "impulse + median": lena_s_m,
    "gaussian + gaussian": lena_g_g,
    "gaussian + average": lena_g_a,
    "gaussian + median": lena_g_m,
}
visualize_grid3x3(results)

Explanation:

Gaussian noise is the least visible noise to the human eye because of the normal distribution using the Gaussian function. Salt and Pepper noise is the most visible noise to the human eye because of the extreme visibility of white and black pixels. Average Filter is the most blurred photo filter. Median Filter is the least blurred photo filter. Even with the addition of different types of noises, Median filter provides the best resolution output.

Programming Task: Sharpening¶

Now write a small program that applies sharpening on above lena images.

In [5]:
# Solution:

# TODO sharpen the smothed images from above.
# Solution
import cv2
import numpy as np
import matplotlib.pyplot as plt

def visualize_grid3x3(results):
    # Visualize the results in a 3x3 image matrix
    ROWS=3; COLS=3
    plt.figure(figsize=(18,18)) # Make a wide figure
    for idx, (title, image) in enumerate(results.items()):
        plt.subplot(ROWS, COLS, idx + 1)  # Select subplot
        plt.title(title)  # Set title to key of dict
        plt.imshow(image[:,:,::-1])  # BGR2RGB
    plt.show()

lena = get_image("lena.png")

#Salt noise (Impulse noise)
def sal_no(im):
    for i in range(1,nopi,10):
        y1=np.random.randint(r)
        x1=np.random.randint(c)
        im[x1][y1] = 255
    return im

#Pepper noise
def pep_no(im):
    for i in range(1,nopi,10):
        y2=np.random.randint(r)
        x2=np.random.randint(c)
        lena[y2][x2] = 0
    return im

#Gaussian noise
def g_no(im):
    row,col,ch = im.shape
    mean = 0 #Mean
    var = 0.1 #Variance
    sig = var**0.5 #Sigma
    gg = np.random.normal(mean,sig,(row,col,ch)) #Guassian normal distribution
    gg = gg.reshape(row,col,ch)
    gaus = im + gg #Appending image with Gaussian distribution
    return gaus

r, c = lena.shape[:-1] #Dimensions of image
nopi = r*c #Number of pixels

#Calling the noise functions
lena_s = sal_no(lena)
lena_sp = pep_no(lena_s)
lena_g = g_no(lena)

ksize = (10,10) #Kernel size

#Gaussian Filter
lena_sp_g = cv2.GaussianBlur(lena_sp,(9,9),0)
lena_s_g = cv2.GaussianBlur(lena_s,(9,9),0)
lena_g_g = cv2.GaussianBlur(lena_g,(9,9),0)

#Average Filter
lena_sp_a = cv2.blur(lena_sp,ksize)
lena_s_a = cv2.blur(lena_s,ksize)
lena_g_a = cv2.blur(lena_g,ksize)

#Median Filter
lena_sp_m = cv2.medianBlur(lena_sp,5)
lena_s_m = cv2.medianBlur(lena_s,5)
lena_g_m = cv2.medianBlur(lena_s,5)

ker = np.array([[0 -1, 0],[-1, 5 -1], [0 -1, 0]]) #Mask

results = { #Filter2D function for Sharpening
    "salt & pepper + gaussian": cv2.filter2D(lena_sp_g, -1, ker),
    "salt & pepper + average": cv2.filter2D(lena_sp_a, -1, ker),
    "salt & pepper + median": cv2.filter2D(lena_sp_m, -1, ker),
    "impulse + gaussian": cv2.filter2D(lena_s_g, -1, ker),
    "impulse + average": cv2.filter2D(lena_s_a, -1, ker),
    "impulse + median": cv2.filter2D(lena_s_m, -1, ker),
    "gaussian + gaussian": cv2.filter2D(lena_s_g, -1, ker),
    "gaussian + average": cv2.filter2D(lena_s_a, -1, ker),
    "gaussian + median": cv2.filter2D(lena_g_m, -1, ker),
}
visualize_grid3x3(results)

4. Fourier Transform and its applications¶

Theory: Fourier¶

  1. Explain how Fourier Transformation and Inverse Fourier Transformation work on a digital image. Explain why it is useful to transform an image from spatial domain into frequency domain.
  2. After transforming an image into frequency domain, explain what kind of image information is saved in high frequency and low frequency.
  3. Explain why Laplacian is a high pass filter, explain that using Fourier Transformation.

Solution: 1.Fourier transform breaks down the image into sum of constituent sine and cosine waves that make up the data. Inverse Fourier transform is used to get back the original image back after the fourier transform is performed by optinally altering the frequency data before running the inverse fourier transform. When the image is transformed to frequency domain from spatial domain, image filtering is used for image enchancemnt for a specific application.

2.Once the image is transformed to frequency domain, in high frequency dowmin, sharpening of the image will be fomred while in low frequency domain smoothing of the image will be formed.

3.High pass filter is the basic requirement for most of the sharpening methods. It is used to retain the high frequency data within in the image and will reduce the low frequency data. The kernel of the high pass filter is created to increase the brightness of the center pixel when compared to neighboring pixels. It usually contains one positive value at the center and surrounded by the negative values. Laplacian filter is used to compute second derivative of an image, which is measures the rate of change in first derivative. This helps in finding adjacent pixel is an edge or continuous. Laplacian kernel contains negative values in cross pattern. The corners will be having either zero or positive value and the center pixel value can be positive or negative. From the above expalnation we can say that Laplacian is an High pass filter.

From defination of Fourier transformation we say that time domian function is continuous sum of exponential functions which means it uses sim of positive and negative frequencies. It is used to solve the differential equations which relatesthe input and output of the function. The first diffrentiation is converted intoalgebraic equation which is manipulated into fourier transform of the output which contains frequency as the response. However, the fourier transform does not exist for many signals and to analyse many complex domain and unstable systems fourier transform cannot be used. In that case Laplace transform is used, which includes exponential convergence factor σ along with jω. After including of this factors the function becomes absolutely integrable. Laplace transform is widely used in solving diffrential since it exists even for signals for which the fourier transform does not exist.

Programming Task: Fourier Transformation¶

In image processing, often only the magnitude of the Fourier Transform is displayed, as it contains most of the information of the geometric structure of the spatial domain image. See the example below:

image.png

Implement Fourier Transformation on a grayscale image (use any), the result should be similar to the given example.

In [6]:
# Solution
import cv2
import numpy as np
import matplotlib.pyplot as plt



# Visualize image and spectrum side by side
def visualize_spectrum(image, spectrum):
    plt.figure(figsize=(18,6))
    plt.subplot(1, 2, 1)
    plt.title("Image")
    plt.imshow(image, cmap="gray")
    plt.subplot(1, 2, 2)
    plt.title("Spectrum")
    plt.imshow(spectrum, cmap="gray")
    plt.show()

messi = get_image("messi.png")
messi_gray = cv2.cvtColor(messi, cv2.COLOR_BGR2GRAY)

#np.fft.fft2 -> function computes n-dimensional FT over M-dimensional array by means of FastFT
fourier = np.fft.fft2(messi_gray)
#zero frequency component (DC component) will be at top left corner.
#to bring it to center, we need to shift the result by {N}/{2} in both the directions
freqShift = np.fft.fftshift(fourier)
#taking the absolute value to see the spectrum
mg_spec = np.abs(freqShift)
#using log for better visualization as it allows you to see details at all amplitudes
magnitude_spectrum = 20*np.log(mg_spec)
visualize_spectrum(messi_gray, magnitude_spectrum)

Programming Task: High Pass Filter¶

Remove the low frequency part by masking (60x60), and transform the image back into spatial domain, please explain what happened.

In [7]:
# Solution

messi = get_image("messi.png")
r, c = messi.shape[:-1]
row,col = r/2 , c/2
row,col = int (row), int(col)

#removing low freq by masking rectangluar windor of 60*60
freqShift[row-30:row+30, col-30:col+30] = 0

#shifting dc componet back to edges
fr_sh = np.fft.ifftshift(freqShift)

#apply inverse fourier transform to get the image back
imgHPF = np.fft.ifft2(fr_sh)

#obtain absolute value since a complex array is derived
imgHPF = np.real(imgHPF)

visualize_spectrum(messi_gray, imgHPF)

Explanation:

The resulting image shows that only the high frequency signals are displayed where as the low frequency signals are removed. Only the edges of the image is displayed as the frequency is higher in the edges

Programming Task: Low Pass Filter¶

Remove the high frequency part, and transform the image back into spatial domain, please explain what happened.

In [8]:
# Solution

messi = get_image("messi.png")

messi_float32 = np.float32(messi_gray)
CvDft = cv.dft(np.float32(messi_float32), flags = cv.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(CvDft)

r, c = messi.shape[:-1]
row,col = r/2 , c/2
row,col = int (row), int(col)

#creating a mask with high freq as 0, low freq as 1
kernel = np.zeros((r, c, 2), np.uint8)
kernel[row-40:row+40, col-40:col+40] = 1

#applying inverse dft and kernel
fshift = dft_shift*kernel
f_ishift = np.fft.ifftshift(fshift)
imgLPF = cv2.idft(f_ishift)
imgLPF_magnitude = cv2.magnitude(imgLPF[:,:,0],imgLPF[:,:,1])

visualize_spectrum(messi_gray,imgLPF_magnitude)

Explanation:

In Low Pass filter, only the low frequencies are passed ingonring the high frequencies by creating a mask with high value 1 at low frequencies and 0 at high frequencies, hence the image is blurred.


5. Integral Histogram of an Image¶

image.png

As shown in the figure, the left side is a grayscale image $I$, and its integral image is shown on the right. In the integral image, each pixel represents the cumulative sum of a corresponding input pixel with all pixels above and to the left of the input pixel. In another word, the (i, j)th element of integral image is equal to the sum of all the pixel values in the upper left corner of the (i, j)th pixel in the original image $I$.

$$ \begin{aligned} I_{integral}(2, 4) &= I(1,1) + I(1,2) + I(1,3) + I (1,4) + I(2,1 ) + I(2,2) + I(2,3) + I(2,4)\\ &= 2 + 1 + 2 + 3 + 3 + 2 + 1 + 2\\ &= 16 \end{aligned} $$

Similarly, the definition of the integral histogram $H$ of an image $I$ is as follows: The integral histogram of an image is equal to the image on size (width and height are equal), and its $(i, j)$th element indicates the histogram obtained by counting the pixel value of all pixels in the upper left corner of the $(i, j)$th pixel of the original image $I$, as shown in the following figure:

image.png

In this example, the range of pixel value of the grayscale image is 0-9. The element $H(4,5)$ of its integral histogram is a histogram of the upper left corner of the $(4,5)$th pixel in the original image. The number of pixels with value 0-9 is 2, 1, 4, 3, 2, 2, 2, 1, 2, 1, correspondingly. So in this case, it has 10 bins, so the integral histogram $H$ should be in size of Height x Width x 10, and $H(4,5) = [2, 1, 4, 3, 2, 2, 2, 1, 2, 1]$.

Programming Task¶

Implement the integral histogram $H$ for a grayscale image and visualize the histogram $H(10,10)$ using matplotlib, please explain the outputs.

Note: This time you are only allowed to use OpenCV to load the image and matplot lib to visualize, implement the function yourself.

Hint: https://www.mathworks.com/help/images/ref/integralimage.html

In [9]:
# Solution
import cv2
import numpy as np
import matplotlib.pyplot as plt


def generate_histogram(input_image,x,y):
    
    #Initializing count and index values to null
    count = [0]*256                      
    index = [] 
    
    #Creating subset of the image based on height and width of histogram
    mask=input_image[0:x,0:y]
    
    #Assigning index values and count = number of pixels with same value
    for i in range(256):
        count[i] = np.count_nonzero(mask == i)

        index.append(i)                            
    return index, count

messi = get_image("messi.png")
messi_gray = cv2.cvtColor(messi, cv2.COLOR_BGR2GRAY)

#Calling the function
index_array,count_array=generate_histogram(messi_gray,10,10)

#Plotting the Histogram
plt.figure()
plt.plot(index_array, count_array)
plt.xlabel("Pixel Value")
plt.ylabel("Number of Pixels")
plt.title("Integral Histogram  -> H(10,10)")
plt.show()

print(messi_gray.shape, messi_gray.dtype, messi_gray.min(), messi_gray.max())

plt.imshow(messi_gray, cmap="gray")
plt.show()
(127, 195) uint8 2 253

Explanation:

The integral histogram of an image is equal to the image on size (width and height are equal), and its (𝑖,𝑗) th element indicates the histogram obtained by counting the pixel value of all pixels in the upper left corner of the (𝑖,𝑗) th pixel of the original image I. The function generate_histogram in the program takes image, height of histogram and width of histogram as arguments. It returns index [pixel value] and the count [count = number of pixels with same value]. And then we used Matplotlib to plot the Histogram H(10,10). X axis in the plot represents pixel values of subset image(H(10,10)) ranging from 0 to 255. Y axis in the plot represents number of pixels with same value. And the plot represents number of occurences of pixel values.

In [ ]: